home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dcpp / direct.c < prev    next >
C/C++ Source or Header  |  1997-09-09  |  8KB  |  399 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6.  
  7. /*
  8.  *  DIRECT.C
  9.  *
  10.  */
  11.  
  12. #include "defs.h"
  13. #ifdef _DCC
  14. #include <lib/misc.h>    /*  get _parseargs1() & 2   */
  15. #endif
  16.  
  17. Prototype short IfEnabled;
  18. Prototype short IfIndex;
  19.  
  20. Prototype void InitDirective(void);
  21. Prototype long HandleDirective(ubyte *, int, int);
  22. Prototype void do_if(ubyte *, int, long *);
  23. Prototype void do_ifndef(ubyte *, int, long *);
  24. Prototype void do_ifdef(ubyte *, int, long *);
  25. Prototype void do_else(ubyte *, int, long *);
  26. Prototype void do_elif(ubyte *, int, long *);
  27. Prototype void do_endif(ubyte *, int, long *);
  28. Prototype void do_pragma(ubyte *, int, long *);
  29. Prototype void do_error(ubyte *, int, long *);
  30. Prototype void do_line(ubyte *, int, long *);
  31. Prototype void do_null(ubyte *, int, long *);
  32. Prototype void do_passthru(ubyte *, int, long *);
  33.  
  34. short IfEnabled = 1;
  35. short IfIndex;
  36.  
  37. static char IfAry[MAX_IF_LEVEL];
  38. static char InElse[MAX_IF_LEVEL];
  39. static char AutoEndif[MAX_IF_LEVEL];    /*  for #elif    */
  40.  
  41. typedef struct Direct {
  42.     short   Len;
  43.     short   IfFlag;
  44.     void    (*Func)(ubyte *, int, long *);
  45.     char    *Name;
  46. } Direct;
  47.  
  48. Direct DirAry[] = {
  49.     {    6,  0,    do_define,  "define"    },
  50.     {    5,  1,    do_ifdef,   "ifdef"     },
  51.     {    6,  1,    do_ifndef,  "ifndef"    },
  52.     {    2,  1,    do_if,        "if"        },
  53.     {    4,  1,    do_else,    "else"      },
  54.     {    4,  1,    do_elif,    "elif"      },
  55.     {    5,  1,    do_endif,   "endif"     },
  56.     {    7,  0,    do_include, "include"   },
  57.     {    6,  0,    do_pragma,  "pragma"    },
  58.     {    5,  0,    do_error,   "error"     },
  59.     {    5,  0,    do_undef,   "undef"     },
  60.     {    4,  0,    do_line,    "line"      },
  61.     {    1, -1,    do_passthru,"#"         },
  62.     {    0,  0,    do_null,    ""          },
  63.     {    -1 }
  64. };
  65.  
  66. void
  67. InitDirective()
  68. {
  69.     IfEnabled = 1;
  70.     IfAry[0] = 1;
  71.     InElse[0] = 0;
  72. }
  73.  
  74. long
  75. HandleDirective(base, i, max)
  76. ubyte *base;
  77. int i;
  78. int max;
  79. {
  80.     long b = i;
  81.     long e;
  82.     long idx;
  83.     Direct *dir;
  84.  
  85.     /*
  86.      *    Determine extent of directive and strip comments.  Comments
  87.      *    are not subject to newline termination.  Strip out newlines as
  88.      *    they can interfere with line numbering.
  89.      */
  90.  
  91.     {
  92.     long n = i;
  93.     long x = i;
  94.  
  95.     while (n < max && base[n] != '\n') {
  96.         if (base[n] == '\'') {
  97.         long n2 = SkipSingleSpec(base, n + 1, max);
  98.         movmem(base + n, base + x, n2 - n);
  99.         x += n2 - n;
  100.         n = n2;
  101.         continue;
  102.         }
  103.         if (base[n] == '\"') {
  104.         long n2 = SkipString(base, n + 1, max);
  105.         movmem(base + n, base + x, n2 - n);
  106.         x += n2 - n;
  107.         n = n2;
  108.         continue;
  109.         }
  110.         if (base[n] == '/') {
  111.         if (base[n+1] == '*') {
  112.             n = SkipComment(base, n + 2, max);
  113.             base[x++] = ' ';
  114.             continue;
  115.         }
  116.         if (base[n+1] == '/' && SlashSlashOpt) {
  117.             n = SkipCommentLine(base, n + 2, max);
  118.             base[x++] = ' ';
  119.             continue;
  120.         }
  121.         }
  122.         if (base[n] == '\\' && base[n+1] == '\n') {
  123.         ++PushBase->LineNo;
  124.         putc('\n', Fo);
  125.         n += 2;
  126.         continue;
  127.         }
  128.         base[x++] = base[n++];
  129.     }
  130.     while (x > i && (base[x-1] == ' ' || base[x-1] == '\t'))
  131.         --x;
  132.     max = x;
  133.     ++PushBase->LineNo;
  134.     e = n;
  135.     }
  136.  
  137.     /*
  138.      *    Skip white space, find the directive.  Allow ## directives through
  139.      *    with no modifications (but #if/#endif will work around them).  If
  140.      *  stripping an include, ignore the directive (simply spit it out)
  141.      */
  142.  
  143.     while (i < max && (base[i] == ' ' || base[i] == 9))     /*  skip ws */
  144.     ++i;
  145.     b = i;
  146.     while (i < max && SymbolChar[base[i]])            /*    directive */
  147.     ++i;
  148.  
  149.     for (dir = DirAry; dir->Len >= 0; ++dir) {
  150.     if (dir->Len == i - b && strncmp(dir->Name, base + b, i - b) == 0)
  151.         break;
  152.     }
  153.  
  154.     while (i < max && (base[i] == ' ' || base[i] == 9))     /*  more ws */
  155.     ++i;
  156.  
  157.     b = i;                            /*    BASE    */
  158.  
  159.     if (dir->Len < 0) {
  160.     if (IfEnabled)
  161.         cerror(EERROR_UNKNOWN_DIRECTIVE);
  162.     putc('\n', Fo);
  163.     return(e+1);
  164.     }
  165.     if (dir->IfFlag <= 0 && IfEnabled == 0) {
  166.     putc('\n', Fo);
  167.     return(e+1);
  168.     }
  169.     if (dir->IfFlag >= 0)
  170.     putc('\n', Fo);
  171.  
  172.     /*
  173.      *    note that max is different from idx.  The stuff between max and idx
  174.      *    is junk.
  175.      */
  176.  
  177.     idx = e + 1;
  178.  
  179.     (*dir->Func)(base + b, max - b, &idx);
  180.  
  181.     return(idx);
  182. }
  183.  
  184. void
  185. do_if(buf, max, pu)
  186. ubyte *buf;
  187. int max;
  188. long *pu;   /*    unused */
  189. {
  190.     short undef;
  191.     long v;
  192.  
  193.     if (IfIndex == MAX_IF_LEVEL)
  194.     cerror(EFATAL_MAX_IFS, MAX_IF_LEVEL);
  195.     if (IfEnabled == 0) {
  196.     ++IfIndex;
  197.     IfAry[IfIndex] = 0;
  198.     InElse[IfIndex] = 0;
  199.     AutoEndif[IfIndex] = 0;
  200.     return;
  201.     }
  202.     v = ParseIfExp(buf, &undef, max, 1);
  203.     if (undef) {
  204.     /* REMOVED, ANSI COMPAT
  205.     cerror(EERROR, "#if : undefined symbol");
  206.     v = 1;
  207.     */
  208.     }
  209.     if (v == 0)
  210.     IfEnabled = 0;
  211.     ++IfIndex;
  212.     IfAry[IfIndex] = IfEnabled;
  213.     InElse[IfIndex] = 0;
  214.     AutoEndif[IfIndex] = 0;
  215. }
  216.  
  217. void
  218. do_ifndef(buf, max, pu)
  219. ubyte *buf;
  220. int max;
  221. long *pu;   /*    unused */
  222. {
  223.     short undef;
  224.  
  225.     ParseIfExp(buf, &undef, max, 0);
  226.     if (undef)
  227.     do_if("1", 1, NULL);
  228.     else
  229.     do_if("0", 1, NULL);
  230. }
  231.  
  232. void
  233. do_ifdef(buf, max, pu)
  234. ubyte *buf;
  235. int max;
  236. long *pu;   /*    unused */
  237. {
  238.     short undef;
  239.  
  240.     ParseIfExp(buf, &undef, max, 0);
  241.     if (undef)
  242.     do_if("0", 1, NULL);
  243.     else
  244.     do_if("1", 1, NULL);
  245. }
  246.  
  247. void
  248. do_else(buf, max, pu)
  249. ubyte *buf;
  250. int max;
  251. long *pu;   /*    unused */
  252. {
  253.     if (InElse[IfIndex]) {
  254.     cerror(EERROR_MULTIPLE_ELSE_FOR_IF);
  255.     return;
  256.     }
  257.     InElse[IfIndex] = 1;
  258.     if (IfIndex && IfAry[IfIndex-1] == 0)
  259.     return;
  260.     IfAry[IfIndex] = 1 - IfAry[IfIndex];
  261.     IfEnabled = IfAry[IfIndex];
  262. }
  263.  
  264. void
  265. do_elif(buf, max, pu)
  266. ubyte *buf;
  267. int max;
  268. long *pu;   /*    unused */
  269. {
  270.     do_else(buf, max, NULL);
  271.     AutoEndif[IfIndex] = 1;
  272.     do_if(buf, max, NULL);
  273. }
  274.  
  275. void
  276. do_endif(buf, max, pu)
  277. ubyte *buf;
  278. int max;
  279. long *pu;   /*    unused */
  280. {
  281.     if (IfIndex == 0) {
  282.     cerror(EERROR_ENDIF_WITHOUT_IF);
  283.     return;
  284.     }
  285.     do {
  286.     --IfIndex;
  287.     IfEnabled = IfAry[IfIndex];
  288.     } while (IfIndex && AutoEndif[IfIndex]);
  289. }
  290.  
  291. /*
  292.  *  #pragma
  293.  *
  294.  *  DCCOPTS - processed by DCPP and passed on
  295.  *  <other> - passed on
  296.  */
  297.  
  298. void
  299. do_pragma(buf, max, pu)
  300. ubyte *buf;
  301. int max;
  302. long *pu;   /*    unused */
  303. {
  304.     if (strncmp(buf, "DCCOPTS", 7) == 0) {
  305. #ifdef _DCC
  306.     /*
  307.      *  Parse #pragma DCCOPTS lines.  Use DICE's argument parser
  308.      *  for main().  I am following the standard argc/argv opts
  309.      *  here with a dummy av[0] and av[n] = NULL to give ParseOpts()
  310.      *  the same format as main() gives it.  This is really not
  311.      *  necessary but what the hell.
  312.      */
  313.  
  314.     char *copy;
  315.     char **av;
  316.     short ac;
  317.  
  318.     movmem(buf, copy = zalloc(max + 1), max);
  319.  
  320.     if (ac = _parseargs1(copy + 7, max - 7)) {
  321.         av = zalloc((ac + 2) * 4);
  322.         _parseargs2(copy + 7, av+1, ac);
  323.         ++ac;
  324.         ParseOpts(ac, av, 0);
  325.     }
  326. #endif
  327.     }
  328.  
  329.     /*
  330.      *    Pragma's are always passed on
  331.      */
  332.  
  333.     Dump("#pragma ", 0, 8);
  334.     Dump(buf, 0, max);
  335.     Dump("\n", 0, 1);
  336. }
  337.  
  338. void
  339. do_null(buf, max, pu)
  340. ubyte *buf;
  341. int max;
  342. long *pu;   /*    unused    */
  343. {
  344.  
  345. }
  346.  
  347. void
  348. do_error(buf, max, pu)
  349. ubyte *buf;
  350. int max;
  351. long *pu;   /*    unused */
  352. {
  353.     cerror(EERROR_ERROR_DIRECTIVE, max, buf);
  354. }
  355.  
  356. /*
  357.  *  # line <lineno> "filename"
  358.  */
  359.  
  360. void
  361. do_line(buf, max, pu)
  362. ubyte *buf;
  363. int max;
  364. long *pu;   /*    unused */
  365. {
  366.     short len = 0;
  367.     Include *pb = PushBase;
  368.  
  369.     pb->LineNo = atoi(buf);
  370.     while (max && *buf != '\"') {
  371.     --max;
  372.     ++buf;
  373.     }
  374.     if (*buf == '\"') {
  375.     ++buf;
  376.     --max;
  377.     while (len < max && buf[len] != '\"')
  378.         ++len;
  379.     if (strlen(pb->FileName) != len || strncmp(pb->FileName, buf, len) != 0) {
  380.         pb->FileName = malloc(len + 1);
  381.         pb->FileName[len] = 0;
  382.         strncpy(pb->FileName, buf, len);
  383.     }
  384.     }
  385.     fprintf(Fo, "# %ld \"%s\" %ld\n", pb->LineNo, pb->FileName, pb->Level);
  386. }
  387.  
  388. void
  389. do_passthru(buf, max, pu)
  390. ubyte *buf;
  391. int max;
  392. long *pu;   /*    unused */
  393. {
  394.     Dump("##", 0, 2);
  395.     Dump(buf, 0, max);
  396.     Dump("\n", 0, 1);
  397. }
  398.  
  399.